﻿using Microsoft.EntityFrameworkCore;
using Windows.Admin.Domain;
using Windows.Infrastructure.Share.Security;
using Windows.SeedWork;
using Windows.Infrastructure.EFCore.Share.Extensions;

namespace Windows.Admin.Infrastructure.EFCore
{
    public partial class AdminDbContext : DbContext
    {
        //protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        //{
        //    string dbConnectionString="Data Source=.;Initial Catalog=System;User ID=sa;Password=19911004";
        //    // 定义要使用的数据库
        //    optionsBuilder.UseSqlServer(dbConnectionString);
        //}
        private readonly ICurrentUser _currentUser;
        public AdminDbContext(DbContextOptions<AdminDbContext> options, ICurrentUser currentUser) : base(options)
        {
            _currentUser = currentUser;
        }

        public virtual DbSet<App> App { get; set; }
        public virtual DbSet<Privilege> Privilege { get; set; }
        public virtual DbSet<Role> Role { get; set; }
        public virtual DbSet<Role_User> Role_User { get; set; }
        public virtual DbSet<User> User { get; set; }
        public virtual DbSet<Organization> Organization { get; set; }
        public virtual DbSet<Role_Organization> Role_Organization { get; set; }
        public virtual DbSet<Organization_Employee> Organization_Employee { get; set; }
        public virtual DbSet<Shortcut> Shortcut { get; set; }
        public virtual DbSet<Employee> Employee { get; set; }
        public virtual DbSet<ChatLink> ChatLink { get; set; }
        public virtual DbSet<ChatMessage> ChatMessage { get; set; }
        public virtual DbSet<Post> Post { get; set; }
        public virtual DbSet<PostLevel> PostLevel { get; set; }
        public virtual DbSet<Post_Employee> Post_Employee { get; set; }
        public virtual DbSet<Role_Post> Role_Post { get; set; }
        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);
            //自动映射
            modelBuilder.ApplyAllConfigurations(System.Reflection.Assembly.GetExecutingAssembly());
            //foreach (var entityType in modelBuilder.Model.GetEntityTypes())
            //{
            //    entityType.GetOrAddProperty("IsEnable", typeof(bool));
            //    var parameter = Expression.Parameter(entityType.ClrType);
            //    var propertyMethodInfo = typeof(EF).GetMethod("Property").MakeGenericMethod(typeof(bool));
            //    var isDeletedProperty = Expression.Call(propertyMethodInfo, parameter, Expression.Constant("IsEnable"));
            //    BinaryExpression compareExpression = Expression.MakeBinary(ExpressionType.Equal, isDeletedProperty, Expression.Constant(true));
            //    var lambda = Expression.Lambda(compareExpression, parameter);
            //    modelBuilder.Entity(entityType.ClrType).HasQueryFilter(lambda);
            //}
        }
        public override Task<int> SaveChangesAsync(CancellationToken cancellationToken = default)
        {
            var changedEntities = SetDefaultFields();

            //没有自动开启事务的情况下,保证主从表插入，主从表更新开启事务。
            var isManualTransaction = false;
            if (!Database.AutoTransactionsEnabled && Database.CurrentTransaction is null && changedEntities > 1)
            {
                isManualTransaction = true;
                Database.AutoTransactionsEnabled = true;
            }

            var result = base.SaveChangesAsync(cancellationToken);

            //如果手工开启了自动事务，用完后关闭。
            if (isManualTransaction)
                Database.AutoTransactionsEnabled = false;

            return result;
        }
        protected virtual int SetDefaultFields()
        {
            var allBasicAuditEntities = ChangeTracker.Entries<ICreateEntity<long>>().Where(x => x.State == EntityState.Added);
            foreach (var entity in allBasicAuditEntities)
            {
                entity.Entity.CreatedBy = _currentUser.Id;
                entity.Entity.CreatedByName = _currentUser.Name;
                entity.Entity.CreatedOn = DateTime.Now;
            }

            var auditFullEntities = ChangeTracker.Entries<IUpdateEntity<long>>().Where(x => x.State == EntityState.Modified || x.State == EntityState.Unchanged);
            foreach (var entity in auditFullEntities)
            {
                entity.Entity.UpdatedBy = _currentUser.Id;
                entity.Entity.UpdatedByName = _currentUser.Name;
                entity.Entity.UpdatedOn = DateTime.Now;
            }

            return ChangeTracker.Entries<Entity>().Count();
        }
    }
}
